/*********************************************************************************** * * Copyright (c) 2015 Kamil Baczkowicz * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * * Kamil Baczkowicz - initial API and implementation and/or initial documentation * */ package pl.baczkowicz.spy.ui.utils; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Optional; import javafx.application.Platform; import javafx.concurrent.Task; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; import javafx.scene.control.ButtonBar.ButtonData; import javafx.scene.control.ButtonType; import javafx.scene.control.ColorPicker; import javafx.scene.control.Dialog; import javafx.scene.control.Label; import javafx.scene.control.PasswordField; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.control.TextInputDialog; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.stage.StageStyle; import javafx.stage.Window; import javafx.util.Pair; import pl.baczkowicz.spy.exceptions.ExceptionUtils; import pl.baczkowicz.spy.ui.controls.WorkerProgressPane; public class DialogFactory { /** * Shows an error dialog. * * @param title Title of the dialog * @param message Message to be displayed */ public static void createErrorDialog(final String title, final String message) { final Alert alert = new Alert(AlertType.ERROR); alert.setTitle(title); alert.setContentText(message); alert.setHeaderText(null); alert.showAndWait(); } public static void createExceptionDialog(final String title, final Exception e) { final Alert alert = new Alert(AlertType.ERROR); alert.setTitle(title); alert.setHeaderText(null); alert.setContentText(e.getMessage() + " - " + ExceptionUtils.getRootCauseMessage(e)); final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); final TextArea textArea = new TextArea(sw.toString()); textArea.setEditable(false); textArea.setWrapText(true); textArea.setMaxWidth(Double.MAX_VALUE); textArea.setMaxHeight(Double.MAX_VALUE); GridPane.setVgrow(textArea, Priority.ALWAYS); GridPane.setHgrow(textArea, Priority.ALWAYS); GridPane content = new GridPane(); content.setMaxWidth(Double.MAX_VALUE); content.add(textArea, 0, 0); alert.getDialogPane().setExpandableContent(content); alert.showAndWait(); } public static void createWarningDialog(final String title, final String message) { Alert alert = new Alert(AlertType.WARNING); alert.setTitle(title); alert.setContentText(message + "."); alert.setHeaderText(null); alert.showAndWait(); } public static Optional<ButtonType> createQuestionDialog(final String title, final String message, final boolean showNoButton) { final Alert alert = new Alert(AlertType.CONFIRMATION); alert.setTitle(title); alert.setContentText(message); alert.setHeaderText(null); if (showNoButton) { alert.getButtonTypes().setAll(ButtonType.CANCEL, ButtonType.NO, ButtonType.YES); } else { alert.getButtonTypes().setAll(ButtonType.CANCEL, ButtonType.YES); } return alert.showAndWait(); } /** * Asks the user for input. * * @return The user's response */ public static Optional<String> createInputDialog(final Window owner, final String title, final String label) { final TextInputDialog dialog = new TextInputDialog(); dialog.setTitle(title); dialog.setHeaderText(null); dialog.setContentText(label); dialog.initOwner(owner); return dialog.showAndWait(); } public static Optional<ButtonType> createQuestionDialog(final String title, final String message) { return createQuestionDialog(title, message, true); } public static Optional<Pair<String, String>> createUsernameAndPasswordDialog( final String title, final String header, final Pair<String, String> userInfo) { // Create the custom dialog final Dialog<Pair<String, String>> dialog = new Dialog<>(); dialog.setResizable(false); dialog.setTitle(title); dialog.setHeaderText(header); // Set the icon dialog.setGraphic(ImageUtils.createIcon("preferences-desktop-user-password-large", 48)); // Set the button types final ButtonType loginButtonType = new ButtonType("Connect", ButtonData.OK_DONE); dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL); // Create the username and password labels and fields final GridPane grid = new GridPane(); grid.setHgap(15); grid.setVgap(15); grid.setPadding(new Insets(15, 100, 15, 15)); final TextField username = new TextField(); username.setPromptText("Username"); username.setText(userInfo.getKey()); final PasswordField password = new PasswordField(); password.setPromptText("Password"); password.setText(userInfo.getValue()); grid.add(new Label("Username:"), 0, 0); grid.add(username, 1, 0); grid.add(new Label("Password:"), 0, 1); grid.add(password, 1, 1); // Set the login button state depending on whether a username was entered final Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType); loginButton.setDisable(username.getText().trim().isEmpty()); // Validate username.textProperty().addListener((observable, oldValue, newValue) -> { loginButton.setDisable(newValue.trim().isEmpty()); }); dialog.getDialogPane().setContent(grid); // Convert the result to a username-password-pair dialog.setResultConverter(dialogButton -> { if (dialogButton == loginButtonType) { return new Pair<>(username.getText(), password.getText()); } return null; }); Platform.runLater(() -> username.requestFocus()); return dialog.showAndWait(); } public static Stage createWindowWithPane(final Node pane, final Scene parentScene, final String title, final double margin) { final Stage stage = new Stage(StageStyle.UTILITY); final AnchorPane content = new AnchorPane(); content.getChildren().add(pane); AnchorPane.setBottomAnchor(pane, margin); AnchorPane.setLeftAnchor(pane, margin); AnchorPane.setTopAnchor(pane, margin); AnchorPane.setRightAnchor(pane, margin); final Scene scene = new Scene(content); scene.getStylesheets().addAll(parentScene.getStylesheets()); stage.initOwner(parentScene.getWindow()); stage.setTitle(title); stage.setScene(scene); return stage; } public static Color createColorChoiceDialog(final Color color, final String title, final String label) { // Create the custom dialog final Dialog<Color> dialog = new Dialog<>(); dialog.setResizable(false); dialog.setTitle(title); dialog.setHeaderText(null); // Set the button types dialog.getDialogPane().getButtonTypes().setAll(ButtonType.APPLY, ButtonType.CANCEL); // Create fields final GridPane grid = new GridPane(); grid.setHgap(15); grid.setVgap(15); grid.setPadding(new Insets(15, 100, 15, 15)); final ColorPicker picker = new ColorPicker(color); grid.add(new Label(label), 0, 0); grid.add(picker, 1, 0); dialog.getDialogPane().setContent(grid); // Convert the result dialog.setResultConverter(dialogButton -> { if (dialogButton == ButtonType.APPLY) { return picker.getValue(); } return null; }); Platform.runLater(() -> picker.requestFocus()); Optional<Color> result = dialog.showAndWait(); if (result.isPresent()) { return result.get(); } else { return color; } } /** * Shows a worker / progress dialog. * * @param readAndProcess The task backing up the dialog */ public static void createWorkerDialog(final Task<?> readAndProcess) { final Alert dialog = new Alert(AlertType.INFORMATION); dialog.setTitle(readAndProcess.getTitle()); dialog.setHeaderText(null); final ButtonType bgButtonType = new ButtonType("Run in background", ButtonData.APPLY); dialog.getButtonTypes().setAll(ButtonType.CANCEL, bgButtonType); final Label progressMessage = new Label(); progressMessage.textProperty().bind(readAndProcess.messageProperty()); dialog.setResultConverter(dialogButton -> { if (dialogButton == ButtonType.CANCEL) { readAndProcess.cancel(); } return null; }); final WorkerProgressPane content = new WorkerProgressPane(dialog); content.setMaxWidth(Double.MAX_VALUE); VBox vbox = new VBox(10, progressMessage, content); vbox.setMaxWidth(Double.MAX_VALUE); vbox.setPrefSize(400, 80); dialog.getDialogPane().setContent(vbox); content.setWorker(readAndProcess); } public static void setUpTextFieldFileOpenButton(final TextField field, final Button button) { button.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(final ActionEvent event) { final FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Select file to open"); final File selectedFile = fileChooser.showOpenDialog(field.getScene().getWindow()); if (selectedFile != null) { field.setText(selectedFile.getAbsolutePath()); } } }); } }